package com.eimf.saf.common.util;

import java.beans.PropertyDescriptor;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.Map;

import org.springframework.beans.BeansException;
import org.springframework.beans.FatalBeanException;

import com.eimf.saf.common.commons.i18n.Ii18n;

/**
 * @author eden
 * @date 2013-11-13 下午5:34:05
 * @Description: 重写SPRING中的BeanUtils。
 */
public class BeanUtils extends org.springframework.beans.BeanUtils
{

    /**
     * 实体拷贝，会拷贝i18n类中的属性。<br>
     * 不复制原始对象属性内容为null的属性。
     * 
     * @param source
     * @param target
     * @throws BeansException
     */
    public static void copyProperties(final Object source, final Object target) throws BeansException
    {
        final Class<?> actualEditable = target.getClass();
        final PropertyDescriptor[] targetPds = BeanUtils.getPropertyDescriptors(actualEditable);
        for (final PropertyDescriptor targetPd : targetPds)
        {
            if (targetPd.getWriteMethod() != null)
            {
                final PropertyDescriptor sourcePd = BeanUtils.getPropertyDescriptor(source.getClass(),
                        targetPd.getName());
                if (sourcePd != null && sourcePd.getReadMethod() != null)
                {
                    try
                    {
                        final Method readMethod = sourcePd.getReadMethod();
                        if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers()))
                        {
                            readMethod.setAccessible(true);
                        }
                        final Object value = readMethod.invoke(source);
                        // 这里判断以下value是否为空 当然这里也能进行一些特殊要求的处理 例如绑定时格式转换等等
                        if (value != null)
                        {
                            final Method writeMethod = targetPd.getWriteMethod();
                            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers()))
                            {
                                writeMethod.setAccessible(true);
                            }
                            writeMethod.invoke(target, value);
                        }
                    } catch (final Throwable ex)
                    {
                        throw new FatalBeanException("Could not copy properties from source to target", ex);
                    }
                }
                if (source instanceof Ii18n && target instanceof Ii18n)
                {
                    final Ii18n sI18n = (Ii18n) source;
                    final Ii18n tI18n = (Ii18n) target;
                    for (final Map.Entry<String, String> item : sI18n.getI18n().entrySet())
                    {
                        tI18n.addI18n(item.getKey(), item.getValue());
                    }
                }
            }
        }
    }
}
